package com.eurasia.assignment.service;

import com.eurasia.assignment.domain.User;
import com.eurasia.assignment.domain.hoj.*;
import com.eurasia.assignment.service.port.out.HOJFullCaseJudgementPersistencePort;
import com.eurasia.assignment.service.port.out.HOJSingleCaseJudgementPersistencePort;
import com.eurasia.assignment.service.port.out.HOJResourcePort;
import com.eurasia.assignment.service.port.out.dto.CreateFullCaseJudgementRequest;
import com.eurasia.assignment.service.port.out.dto.CreateFullCaseJudgementResponse;
import com.eurasia.assignment.service.port.out.dto.HOJResource;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import com.eurasia.assignment.controller.dto.CreateCodeSubmissionResponse;
import com.eurasia.assignment.controller.dto.ProblemQuery;

import lombok.RequiredArgsConstructor;

import java.util.Objects;

@Service
@RequiredArgsConstructor
public class HOJResourceService {
    private static final Logger log = LoggerFactory.getLogger(HOJResourceService.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();
    private final SecurityContext securityContext;
    
    private final HOJResourcePort hojResourcePort;
    private final HOJSingleCaseJudgementPersistencePort hojResourcePersistencePort;
    private final HOJFullCaseJudgementPersistencePort hojFullCaseJudgementPersistencePort;

    public ResponseEntity<String> getProblems(ProblemQuery query) {
        return hojResourcePort.getProblems(query);
    }

    public ResponseEntity<String> getProblemById(String id) {
        return hojResourcePort.getProblemDetail(id);
    }

    public ResponseEntity<CreateCodeSubmissionResponse> createSingleCaseJudgement(CodeInfo body) throws JsonProcessingException {
        ResponseEntity<CreateCodeSubmissionResponse> response = hojResourcePort.createCodeSubmission(body);
        String key = response.getBody().getData();
        User currentUser = securityContext.getCurrentUser();
        String codeInfo  = objectMapper.writeValueAsString(body);
        HOJSingleCaseJudgement submission = HOJSingleCaseJudgement.builder()
                .codeInfo(codeInfo)
                .submitterId(currentUser.getId())
                .status(HOJJudgementStatus.PENDING)
                .testJudgeKey(key)
                .problemId(body.getPid())
                .build();
        log.debug("创建HOJ代码提交，题目ID: {}, 测试判题Key: {}", body.getPid(), key);
        hojResourcePersistencePort.save(submission);
        return response;
    }

    public ResponseEntity<HOJResource<CreateFullCaseJudgementResponse>> createFullCaseJudgement(CreateFullCaseJudgementRequest request) {
        ResponseEntity<HOJResource<CreateFullCaseJudgementResponse>> response = hojResourcePort.createFullCaseJudgement(request);
        HOJFullCaseJudgement judgement = HOJFullCaseJudgement.builder()
                .runId(Objects.requireNonNull(response.getBody()).getData().getSubmitId())
                .problemId(request.getRawId())
                .problemNo(request.getPid())
                .language(request.getLanguage())
                .submittedCode(request.getCode())
                .status(HOJJudgementStatus.PENDING)
                .submitterId(securityContext.getCurrentUser().getId())
                .build();
        hojFullCaseJudgementPersistencePort.save(judgement);
        return response;
    }

    public ResponseEntity<String> getJudgementResult(String testJudgeKey) {
        // 首先从repo中获取
        HOJSingleCaseJudgement submission = hojResourcePersistencePort
                .findByTestJudgeKey(testJudgeKey).orElseThrow(() -> new IllegalArgumentException("TestJudgeKey not found: " + testJudgeKey));

        if (submission.getResult() != null) {
            return ResponseEntity.ok(submission.getResult());
        }

        ResponseEntity<String> response = hojResourcePort.getTestJudgementResult(testJudgeKey);
        submission.setResult(response.getBody());

        // 解析结果并设置正确的状态
        if (response.getBody() != null) {
            try {
                JudgeResult judgeResult = objectMapper.readValue(response.getBody(), JudgeResult.class);
                if (judgeResult.getData() != null) {
                    // 根据data.status设置状态
                    int statusCode = judgeResult.getData().getStatus();
                    submission.setStatus(mapToHOJSubmissionStatus(statusCode));
                    log.debug("设置提交状态: {} 基于状态码: {}", submission.getStatus(), statusCode);
                } else {
                    log.warn("判题结果中缺少data字段: {}", judgeResult);
                    submission.setStatus(HOJJudgementStatus.FAILED);
                }
            } catch (Exception e) {
                log.error("解析判题结果时出错: ", e);
                submission.setStatus(HOJJudgementStatus.FAILED);
            }
        } else {
            log.warn("判题结果为空");
            submission.setStatus(HOJJudgementStatus.FAILED);
        }
        
        hojResourcePersistencePort.save(submission);

        return response;
    }
    
    /**
     * 将判题系统的status code映射到HOJSubmissionStatus枚举
     */
    private HOJJudgementStatus mapToHOJSubmissionStatus(int statusCode) {
        switch (statusCode) {
            case 0:
                return HOJJudgementStatus.ACCEPTED; // passed
            case -1:
                return HOJJudgementStatus.WRONG_ANSWER; // wrong_answer
            case -2:
                return HOJJudgementStatus.COMPILE_ERROR; // compile_error
            case -3:
                return HOJJudgementStatus.RUNTIME_ERROR; // runtime_error
            case -4:
                return HOJJudgementStatus.TIME_LIMIT_EXCEEDED; // time_limit_exceeded
            case -5:
                return HOJJudgementStatus.MEMORY_LIMIT_EXCEEDED; // memory_limit_exceeded
            default:
                return HOJJudgementStatus.FAILED; // failed
        }
    }
}
